<?php

namespace App\Services\Chat\User;

use App\Enums\FriendApplyEnum;
use App\Enums\FriendStatusEnum;
use App\Enums\MsgStatusEnum;
use App\Events\MessageReplied;
use App\Events\MyWebSocketEvent;
use App\Exceptions\AdminException;
use App\Http\Requests\Admin\LoginRequest;
use App\Models\Chat\ChatFriendApplyModel;
use App\Models\Chat\ChatFriendModel;
use App\Models\Chat\ChatGroupModel;
use App\Models\Chat\ChatGroupUsersModel;
use App\Models\Chat\ChatMessageModel;
use App\Models\ChatUserModel;
use App\Models\ChatUsers;
use App\Services\BaseService;
use App\Managers\Chat\User\ChatUserManager;
use App\Util\ChatUtil;
use Carbon\Carbon;
use GatewayWorker\Lib\Gateway;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Support\Facades\Cookie;

class ChatUserService extends BaseService
{
    public function __construct(ChatUserManager $manager)
    {
        parent::__construct();
        $this->manager = $manager;

        // 设置GatewayWorker服务的Register服务id和端口
        Gateway::$registerAddress = '192.168.30.8:1238';;
    }

    public function userInfo($id)
    {
        return ChatUsers::where('id',$id)->first();
    }
    public function updateUserInfo()
    {
        $id = ChatUtil::getChatId();
        // 更改的字段
        $field = $this->getData('field');
        $value = $this->getData('value');
        if (empty($field) || empty($value)) throw new AdminException('值不能为空');
        ChatUserModel::where('id',$id)->update([
            $field => $value
        ]);

        if ($field == 'nickname'){
            $pinyin = ChatUtil::getFirstChar($value);
            ChatUserModel::where('id',$id)->update([
                'pinyin' => $pinyin
            ]);
        }

        return [];
    }

    public function friends()
    {
        $my_id = ChatUtil::getChatId();
        $friend_list = ChatFriendModel::query()->where('uid',$my_id)
            ->where('status',FriendStatusEnum::GoodFriend)
            ->with('friendInfo')
            ->get()->toArray();
        return $this->format_lists($friend_list);
    }

    public function format_lists($lists)
    {
        foreach ($lists as &$list){
            $remark = $list['remark'];
            $friendInfo = $list['friend_info'];
            $friendInfo['remark'] = $remark;
            $list['friend_info'] = $friendInfo;
        }
        return $lists; // 返回更新后的数组
    }

    public function groupFriends()
    {
        $my_id = ChatUtil::getChatId();

        $friends = ChatFriendModel::query()->where('uid', $my_id)->with('friendInfo')->orderBy('group_sort')->get()->toArray();

        // 初始化一个空数组来存储分组信息
        $friendGroups = [];

        // 遍历所有好友信息
        foreach ($friends as $friend) {
            $id = data_get($friend, 'id', 0);
            $groupName = data_get($friend, 'group_name', '默认分组');
            $remark = data_get($friend, 'remark', '');

            // 如果分组不存在，则初始化一个新的分组
            if (!isset($friendGroups[$groupName])) {
                $friendGroups[$groupName] = [
                    'id' => $id,
                    'head' => $groupName,
                    'body' => [],
                    'open' => true,
                ];
            }

            // 将好友信息添加到对应的分组中
            $friend_infos = data_get($friend, 'friend_info', []);
            $friend_infos['remark'] = $remark;
            $friendGroups[$groupName]['body'][] = $friend_infos;
        }

        // 将分组数组转换为需要的格式
        $lists = array_values($friendGroups);
        return $lists;
    }

    public function updateGroupName()
    {
        $my_id = ChatUtil::getChatId();
        $old_group_name = $this->getData('old_group_name');
        $new_group_name = $this->getData('new_group_name');

        if (empty($old_group_name)) throw new AdminException('分组名不能为空');

        ChatFriendModel::where('uid',$my_id)->where('group_name',$old_group_name)->update([
            'group_name' => $new_group_name
        ]);
        return [];
    }

    public function updateRemark()
    {
        $my_id = ChatUtil::getChatId();
        $fid = $this->getData('fid');
        $new_remark = $this->getData('new_remark');

        //备注首字母
        $f_nickname = ChatUserModel::where('id',$fid)->value('nickname');
        $pinyin = ChatUtil::getFirstChar($f_nickname);
        if (!empty($new_remark)){
            $pinyin = ChatUtil::getFirstChar($new_remark);
        }

        ChatFriendModel::where('uid',$my_id)->where('fid',$fid)->update([
            'remark' => $new_remark,
            'pinyin' => $pinyin,
        ]);
        return [];
    }

    public function searchFriend()
    {
        $search_key = $this->getData('search_key');
        $list = ChatUsers::query()->where('account',$search_key)->orWhere('phone',$search_key)->first();
        if (empty($list)) throw new AdminException('该用户不存在');
        // 判断是否搜索自己账号
        $is_own = $list['id'] == ChatUtil::getChatId();
        if ($is_own) throw new AdminException('不能添加自己为好友');
        // 判断是否已经是好友
        $has_friend = ChatFriendModel::query()->where('uid',ChatUtil::getChatId())->where('fid',$list['id'])->where('status',FriendStatusEnum::GoodFriend)->first();
        $is_friend = 0;
        if ($has_friend) {
            $is_friend = 1;
        }
        data_set($list,'is_friend',$is_friend);
        // 如果是待审核状态
        $if_pending = ChatFriendModel::query()->where('uid',ChatUtil::getChatId())->where('fid',$list['id'])->where('status',FriendStatusEnum::PendingPass)->first();
        if ($if_pending) throw new AdminException('请等待对方通过');
        return $list;
    }

    public function addFriend()
    {
        // 申请信息
        $apply_msg = $this->getData('apply_msg');
        // 备注
        $remark = $this->getData('remark');
        // 好友id
        $fid = $this->getData('fid');
        // 本人id
        $uid = ChatUtil::getChatId();

        if (empty($apply_msg)) throw new AdminException('申请信息不能为空');
        if (empty($fid)) throw new AdminException('好友id不能为空');

        // 判断是否已是好友
        $if_friend = ChatFriendModel::query()->where('uid',$uid)->where('fid',$fid)->where('status',FriendStatusEnum::GoodFriend)->first();
        if ($if_friend) throw new AdminException('该用户已经是您的好友');
        // 是否待通过状态
        $if_pending = ChatFriendModel::query()->where('uid',$uid)->where('fid',$fid)->where('status',FriendStatusEnum::PendingPass)->first();
        if ($if_pending) throw new AdminException('请等待对方通过');

        $f_nickname = ChatUserModel::where('id',$fid)->value('nickname');
        $pinyin = ChatUtil::getFirstChar($f_nickname);
        if (!empty($remark)){
            $pinyin = ChatUtil::getFirstChar($remark);
        }

        try {
            \DB::beginTransaction();

            ChatFriendModel::create([
                'uid' => $uid,
                'fid' => $fid,
                'remark' => $remark,
                'pinyin' => $pinyin,
                'status' => FriendStatusEnum::PendingPass,
                'add_time' => now()
            ]);

            ChatFriendApplyModel::create([
                'fid' => $uid,
                'tid' => $fid,
                'msg' => $apply_msg,
                'create_time' => now(),
                'status' => FriendApplyEnum::Pending
            ]);
            \DB::commit();
        } catch (\Throwable $e) {
            \DB::rollBack();
            throw new AdminException('添加好友失败：'.$e->getMessage());
        }
        return [];
    }

    public function friendApplyList()
    {
        $fid = ChatUtil::getChatId();
        $list = ChatFriendApplyModel::query()
            ->where(function ($query) use ($fid) {
                $query->where('fid', $fid)
                      ->orWhere('tid', $fid);
            })
            ->with('tInfo','fInfo')
            ->orderBy('create_time','desc')
            ->get()
            ->map(function ($item) use ($fid) {
                $item->is_initiator = $item->fid == $fid ? '我添加对方' : '对方添加我';
                return $item;
            })
            ->toArray();

        return $list;
    }

    public function newFriendNum()
    {
        $my_id = ChatUtil::getChatId();
        $newFriendNum = ChatFriendApplyModel::where('tid',$my_id)
            ->where('status',FriendApplyEnum::Pending)
            ->count();
        return [
          'newFriendNum' => $newFriendNum,
        ];
    }
    public function getNewFriend()
    {
        $apply_id = $this->getData('apply_id');
        $fid = ChatFriendApplyModel::where('id',$apply_id)->value('fid');
        $tid = ChatFriendApplyModel::where('id',$apply_id)->value('tid');

        if ($fid == ChatUtil::getChatId()){
            $other_id = $tid;
        }else{
            $other_id = $fid;
        }
        $info = ChatUsers::query()->where('id',$other_id)->first();
        return $info;
    }

    public function agreeNewFriend()
    {
        // 本人id
        $my_id = ChatUtil::getChatId();
        // 对方id
        $other_id = $this->getData('other_id');
        // 备注
        $remark = $this->getData('remark');

        try {
            \DB::beginTransaction();

            // 将申请记录的状态改为同意
            ChatFriendApplyModel::query()->where('tid',$my_id)->where('fid',$other_id)->update(['status'=>FriendApplyEnum::Agree]);
            ChatFriendApplyModel::query()->where('tid',$other_id)->where('fid',$my_id)->update(['status'=>FriendApplyEnum::Agree]);

            // 好友列表新增记录 对方如果存在未通过的记录改为已通过
            ChatFriendModel::where('uid',$other_id)->where('fid',$my_id)
                ->where('status',FriendStatusEnum::PendingPass)->update(['status'=>FriendStatusEnum::GoodFriend]);

            //备注首字母
            $f_nickname = ChatUserModel::where('id',$other_id)->value('nickname');
            $pinyin = ChatUtil::getFirstChar($f_nickname);
            if (!empty($remark)){
                $pinyin = ChatUtil::getFirstChar($remark);
            }

            ChatFriendModel::create([
                'uid' => $my_id,
                'fid' => $other_id,
                'remark' => $remark,
                'pinyin' => $pinyin,
                'status' => FriendStatusEnum::GoodFriend,
                'add_time' => now()
            ]);

            \DB::commit();
        } catch (\Throwable $e){
            \DB::rollBack();
            throw new AdminException('同意好友申请失败：'.$e->getMessage());
        }

        return [];
    }

    // 用户连接websocket时 绑定uid
    public function bindClientId()
    {
        $client_id = $this->getData('client_id');
        $uid = ChatUtil::getChatId();

        if (!empty($client_id)){
            Gateway::bindUid($client_id,$uid);
        }

        // 初始化连接时 获取用户的好友ids 将好友ids分别创建群组
        $friend_ids = ChatFriendModel::query()->where('uid',$uid)->where('status',FriendStatusEnum::GoodFriend)->pluck('fid')->toArray();
        // 用户存在的房间ids
        $group_ids = ChatGroupUsersModel::where('uid',$uid)->distinct()->pluck('group_id')->toArray();
        foreach ($group_ids as $group_id){
            $other_uid = ChatGroupUsersModel::where('group_id',$group_id)->where('uid','<>',$uid)->pluck('uid')->toArray();
            // 说明是单聊
            if (count($other_uid) == 1) {
                // todo 群聊
                if (!in_array($other_uid[0],$friend_ids)){

                }
                // 单聊
                //将用户加入组
                Gateway::joinGroup($client_id,$group_id);
                //改为在线状态
                ChatGroupUsersModel::where('group_id',$group_id)
                    ->where('uid',$uid)
                    ->update([
                       'is_online' => 1
                    ]);
            }
        }
//        $data = [
//            'type' => 'msg',
//            'data' => [
//                'client_id' => $client_id,
//                'uid' => $uid,
//                'content' => '进入聊天室'
//            ]
//        ];
//        Gateway::sendToUid($uid,json_encode($data));
        return [];
    }


    public function sendMsg()
    {
        // 谁发的
        $uid = (int)ChatUtil::getChatId();
        // 发送给谁
        $tid = (int)$this->getData('tid');
        // 消息内容
        $content = $this->getData('content');
        // 消息类型  1文字 2图片 3语音
        $msg_type = (int)$this->getData('msg_type');

        //消息状态
        $status = MsgStatusEnum::Unread;
        // 对方是否在线
        $other_online = ChatGroupUsersModel::where('uid',$tid)->value('is_online');
        // 对方是否在房间里
        $in_group = ChatGroupUsersModel::where('uid',$tid)->value('in_group');
        if ($other_online == 1 && $in_group == 1){
            $status = MsgStatusEnum::Read;
        }

        // 封装消息对象
        $data = [
            'type' => 'msg',
            'fid' => $uid,
            'uid' => $tid,
            'content' => $content,
            'msg_type' => $msg_type,
            'status' => $status,
        ];

        // 获取两个人的房间id
        $my_group_ids = ChatGroupUsersModel::where('uid',$uid)->distinct()->pluck('group_id')->toArray();
        $group_id = ChatGroupUsersModel::whereIn('group_id',$my_group_ids)->where('uid','<>',$uid)->where('uid',$tid)->value('group_id');
        if (!$group_id) $group_id = $this->createGroup($uid,$tid); //没有房间即创建房间
        if (!empty($content) && !empty($group_id)){
            ChatMessageModel::create([
                'group_id' => $group_id,
                'fid' => $uid,
                'tid' => $tid,
                'msg' => $content,
                'type' => $msg_type,
                'status' => $status,
                'read_at' => $status == 1 ? Carbon::now()->toDateTimeString() : null,
            ]);
        }

        Gateway::sendToGroup($group_id,json_encode($data));
        return ['is_read'=>$status];
    }

    // 历史消息
    public function msgHistory()
    {
        // 跟谁的聊天记录
        $tid = $this->getData('tid');
        // 本人id
        $my_id = ChatUtil::getChatId();

        $has_history = ChatMessageModel::where(['fid'=>$my_id, 'tid'=>$tid])->orWhere(['fid'=>$tid, 'tid'=>$my_id])->get()->toArray();
        $my_group_ids = ChatGroupUsersModel::where('uid',$my_id)->distinct()->pluck('group_id')->toArray();
        $group_id = ChatGroupUsersModel::whereIn('group_id',$my_group_ids)->where('uid','<>',$my_id)->where('uid',$tid)->value('group_id');
        if (!$group_id) $group_id = $this->createGroup($my_id,$tid); //没有房间即创建房间

        // 未存在聊天记录 且 未创建过房间
        if (empty($has_history) && empty($group_id)){
            $this->createGroup($my_id,$tid);
        }

        $list = ChatGroupModel::where('id',$group_id)
            ->with(['messageList'])
            ->first();

        return $list;
    }

    //创建房间
    public function createGroup($my_id,$tid)
    {
        $group_id = ChatGroupModel::insertGetId([
            'created_by_user_id' => $my_id,
            'created_at' => Carbon::now()->toDateTimeString(),
            'updated_at' => Carbon::now()->toDateTimeString(),
        ]);
        $group_user_ids = [$my_id,$tid];
        foreach ($group_user_ids as $group_user_id){
            ChatGroupUsersModel::create([
                'group_id' => $group_id,
                'uid' => $group_user_id
            ]);
        }
        return $group_id;
    }


    public function userLogout()
    {
        //断连方的id
        $client_id = $this->getData('client_id');
        $uid = Gateway::getUidByClientId($client_id);

        // 将状态改为离线
        ChatGroupUsersModel::where('uid',$uid)->update([
            'is_online' => 0
        ]);

        return [];
    }

    public function comingOrLeaveGroup()
    {
        // 我的id
        $my_id = $this->getData('my_id');
        if (empty($my_id)) $my_id = ChatUtil::getChatId();
        // 对方id
        $tid = $this->getData('tid');
        // 类型
        $type = $this->getData('type');

        if (empty($my_id) || empty($tid) || empty($type)) throw new AdminException('参数错误');

        // 获取房间号
        $my_group_ids = ChatGroupUsersModel::where('uid',$my_id)->distinct()->pluck('group_id')->toArray();
        $group_id = ChatGroupUsersModel::whereIn('group_id',$my_group_ids)->where('uid','<>',$my_id)->where('uid',$tid)->value('group_id');

        if ($type == 'in'){ //进入
            ChatGroupUsersModel::where('group_id',$group_id)->where('uid',$my_id)->update([
               'in_group' => 1
            ]);
            // 获取所有未读消息的ID
            $unReadMessageIds = ChatMessageModel::where(['fid' => $tid, 'tid' => $my_id])
                ->where('status', 0)
                ->pluck('id')
                ->toArray();
            // 批量更新这些消息的状态为已读
            if (!empty($unReadMessageIds)) {
                ChatMessageModel::whereIn('id', $unReadMessageIds)
                    ->update([
                        'status' => MsgStatusEnum::Read,
                        'read_at' => Carbon::now()->toDateTimeString(),
                    ]);
            }
        } elseif ($type == 'out'){  //离开
            ChatGroupUsersModel::where('group_id',$group_id)->where('uid',$my_id)->update([
                'in_group' => 0
            ]);
        }
        return [];
    }
}
